package com.mjk.common.core.jdbc.service.log;

import com.mjk.common.base.model.BaseEntity;
import com.mjk.common.base.model.BaseExample;
import com.mjk.common.core.jdbc.service.plus.idbservice.BaseDBService;
import com.mjk.common.core.jdbc.util.TableUtils;
import com.mjk.common.core.jdbc.util.provider.SelectSqlProvider;
import com.mjk.common.core.jdbc.util.provider.SqlProvider;
import com.mjk.common.tools.gson.GsonUtils;
import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.util.NumberUtils;
import com.mjk.common.util.ObjectUtils;
import com.mjk.common.util.ReflectionUtils;
import org.springframework.stereotype.Service;

import java.util.*;


/**
 * 业务扩展需要，扩展BaseDbService ,记录日志
 * @author mjk
 *
 */
@Service
public class LogBaseDBService {
	private final BaseDBService baseDBService;

	public LogBaseDBService(BaseDBService baseDBService) {
		this.baseDBService = baseDBService;
	}

	/**
	 * 扩展basedbservice 的 update方法
     */
	public Integer update(Object dto,Object ...objects ){
		return this.update(null, null, dto, objects);
	}
	public Integer update(Object mapper,String methodName,Object dto,Object ...objects ){		
		Class<?>[] clazzs = new Class<?>[objects.length];
		for(int i=0;i<objects.length;i++){
			if(null == mapper){
				clazzs[i] = objects[i].getClass().getSuperclass();
			}else{
				clazzs[i] = objects[i].getClass();
			}
		}
		Object o;
		if(ObjectUtils.isEmpty(mapper)&&ObjectUtils.isEmpty(methodName)){
			o= ReflectionUtils.invoke(baseDBService, "update", clazzs, objects);
		}else{
			o = ReflectionUtils.invoke(mapper, methodName, clazzs, objects);
		}
		if (o != null&&Integer.parseInt(o.toString())>0) {//有执行结果在记录日志
			buildRecord(dto,objects);
            return NumberUtils.intValue(o.toString());
        }
        return 0;
	}
	/**
	 * 插入扩展
     */
	public Integer insert(Object dto,Object...objects){
		return this.insert(null, null, dto, objects);
	}
	
	public Integer insert(Object mapper,String methodName,Object dto,Object...objects){
		Class<?>[] clazzs = new Class<?>[objects.length];
		Object o;
		for(int i=0;i<objects.length;i++){
			if(null == mapper){
				clazzs[i] = objects[i].getClass().getSuperclass();
			}else{
				clazzs[i] = objects[i].getClass();
			}
		}
		if(ObjectUtils.isEmpty(mapper)&&ObjectUtils.isEmpty(methodName)){
			o= ReflectionUtils.invoke(baseDBService, "save", clazzs, objects);
		}else{
			o = ReflectionUtils.invoke(mapper, methodName, clazzs, objects);
		}		
		if (o != null&&Integer.parseInt(o.toString())>0) {
			buildRecord(dto,objects);
            return NumberUtils.intValue(o.toString());
        }
        return 0;
	}
	/**
	 * 删除扩展
     */
	public Integer delete(Object dto,Object...objects){
		return this.delete(null, null, dto, objects);
	}
	public Integer delete(Object mapper,String methodName,Object dto,Object...objects){
		Class<?>[] clazzs = new Class<?>[objects.length];
		for(int i=0;i<objects.length;i++){
			if(null == mapper){
				clazzs[i] = objects[i].getClass().getSuperclass();
			}else{
				clazzs[i] = objects[i].getClass();
			}
		}
		Object o;
		if(ObjectUtils.isEmpty(mapper)&&ObjectUtils.isEmpty(methodName)){
			o= ReflectionUtils.invoke(baseDBService, "delete", clazzs, objects);
		}else{
			o = ReflectionUtils.invoke(mapper, methodName, clazzs, objects);
		}		
		if (o != null&&Integer.parseInt(o.toString())>0) {
			buildRecord(dto,objects);
            return NumberUtils.intValue(o.toString());
        }
        return 0;
	}
	
	@SuppressWarnings({ "unchecked" })
	public void buildRecord(Object dto,Object...objects){
		String recordMap = "recordMap";
		if(ObjectUtils.isEmpty(ReflectionUtils.getField(dto.getClass(), recordMap))){
			return;
		}
		List<Map<String,Map<String,Object>>> map = 
				(List<Map<String, Map<String, Object>>>) ReflectionUtils.getFieldValue(dto, recordMap);
		if(null == map){
			map = new ArrayList<>();
		}
		Map<String,Map<String,Object>> itemMap = new HashMap<>();
		Map<String,Object> item = new HashMap<>();
		try{
			if(objects.length>1){//update
				if(objects[0] instanceof BaseEntity entity && objects[1] instanceof BaseExample example){
					String sql = "select %s from %s where %s";
                    String fieldStr = SelectSqlProvider.getSelectFiled(entity);
					String tabName = TableUtils.getTableName(entity);
                    String whereStr = SelectSqlProvider.getQueryCondition(example);
					item.put(LogConstns.OLD_DATE, String.format(sql, fieldStr,tabName,whereStr));
					item.put(LogConstns.NEW_DATE, GsonUtils.bean2Json(entity));
					item.put(LogConstns.TABLE_NAME, tabName);
					item.put(LogConstns.PRIMARY_KEY, whereStr);
					item.put(LogConstns.PRIMARY_VALUE, whereStr);
					itemMap.put(LogConstns.UPDATE,item);
				}else{
					//do notiong
				}
			}else{
				if(objects[0] instanceof BaseEntity entity){//insert
					item.put(LogConstns.NEW_DATE, GsonUtils.bean2Json(entity));
					item.put(LogConstns.TABLE_NAME, TableUtils.getTableName(entity));
                    item.put(LogConstns.PRIMARY_KEY, SqlProvider.getPramaryKeys(entity));
                    item.put(LogConstns.PRIMARY_VALUE, SqlProvider.getPrimaryValues(entity));
					itemMap.put(LogConstns.INSERT,item);
				}else if(objects[0] instanceof BaseExample example){//del
					String sql = "delete from %s where %s";
                    String whereStr = SelectSqlProvider.getQueryCondition(example);
                    String tabName = TableUtils.getTableName(Objects.requireNonNull(SqlProvider.getEntityFromExample(example)));
					item.put(LogConstns.OLD_DATE,  String.format(sql, tabName,whereStr));
					item.put(LogConstns.TABLE_NAME, tabName);
					item.put(LogConstns.PRIMARY_KEY, whereStr);
					item.put(LogConstns.PRIMARY_VALUE, whereStr);
					itemMap.put(LogConstns.DELETE,item);
				}else{
					//do notiong
				}
			}
		}catch(Exception e){
			BizLogger.error(e);
		}
		map.add(itemMap);
		ReflectionUtils.setFieldValue(dto, "recordMap", map);
	}	
}
